﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace ST.Common.Util.Text
{
	/// <summary>
	/// 随机数生成器
	/// </summary>
	public class RandomGenerator
	{
		///// <summary>
		///// 生成随机密码
		///// </summary>
		///// <param name="length"></param>
		///// <param name="numberOfNonAlphanumericCharacters"></param>
		///// <returns></returns>
		//public string RandomPasswd(int length, int numberOfNonAlphanumericCharacters)
		//{
		//	Membership.GeneratePassword(length, numberOfNonAlphanumericCharacters);
		//}

		/// <summary>
		/// 生成随机字符串，随机串包含字母或数字
		/// </summary>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string GetRandomStr(int length)
		{
			return BitConverter.ToString(GetRandomBytes(length));
		}

		/// <summary>
		/// 生成随机数
		/// </summary>
		/// <param name="minValue">最小值（包含）</param>
		/// <param name="maxValue">最大值（不包含）</param>
		/// <returns></returns>
		public static int GetRandomInt(int minValue, int maxValue)
		{
			if (minValue >= maxValue)
			{
				throw new ArgumentOutOfRangeException("参数最大值必须大于参数最小值");
			}
			long diff = (long)maxValue - minValue;
			long upperBound = uint.MaxValue / diff * diff;

			uint ui;
			do
			{
				ui = GetRandomUInt();
			} while (ui >= upperBound);
			return (int)(minValue + (ui % diff));
		}

		/// <summary>
		/// 生成随机unit
		/// </summary>
		/// <returns></returns>
		public static uint GetRandomUInt()
		{
			var randomBytes = GetRandomBytes(sizeof(uint));
			return BitConverter.ToUInt32(randomBytes, 0);
		}

		/// <summary>
		/// 生成随机字节数值
		/// </summary>
		/// <param name="bytesNumber"></param>
		/// <returns></returns>
		public static byte[] GetRandomBytes(int bytesNumber)
		{
			byte[] buffer = new byte[bytesNumber];
			using (RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider())
			{
				csp.GetBytes(buffer);
			}
			return buffer;
		}

		///// <summary>
		///// 根据当前系统时间加随机序列来生成订单号
		///// </summary>
		///// <returns></returns>
		//public static string GenerateOutTradeNo()
		//{
		//	var ran = new Random();
		//	return string.Format("{0}{1}{2}", WxPayConfig.GetConfig().GetMchID(), DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999));
		//}

		/// <summary>
		/// 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
		/// </summary>
		/// <returns></returns>
		public static long GetTimeStamp()
		{
			TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
			return Convert.ToInt64(ts.TotalSeconds);
		}

		/// <summary>
		/// 生成JS里面的日期new Date(xxx)，和js里面日期的getTime()相同
		/// </summary>
		/// <returns></returns>
		public static long GetJSTime(DateTime? dt = null)
		{
			if (!dt.HasValue)
			{
				dt = DateTime.UtcNow;
			}
			TimeSpan ts = dt.Value - new DateTime(1970, 1, 1, 0, 0, 0, 0);
			return Convert.ToInt64(ts.TotalMilliseconds);
		}

		/// <summary>
		/// 生成32位随机字符串
		/// </summary>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string GetNonceStr()
		{
			return Guid.NewGuid().ToString("N");
			//return GetRandomUInt().ToString();
		}

		/// <summary>
		/// 生成指定长度的随机字符串（包含大小写字母、数字）
		/// </summary>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string GetNonceStr(int length)
		{
			var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
			var rand = new Random();
			string str = "";
			for (int i = 0; i < length; i++)
			{
				str += chars[rand.Next(chars.Length)];
				//str += chars[GetRandomInt(0, chars.Length)];
			}
			return str;
		}

		/// <summary>
		/// 生成随机中文名
		/// </summary>
		/// <returns></returns>
		public static string GetRandomName()
		{
			string[] firstNames = @"赵,钱,孙,李,周,吴,郑,王,冯,陈,褚,卫,蒋,沈,韩,杨,朱,秦,尤,许,何,吕,施,张,孔,曹,严,华,金,魏,陶,姜, 戚,谢,邹,喻,柏,水,窦,章,云,苏,潘,葛,奚,范,彭,郎,鲁,韦,昌,马,苗,凤,花,方,俞,任,袁,柳,丰,鲍,史,唐, 费,廉,岑,薛,雷,贺,倪,汤,滕,殷,罗,毕,郝,邬,安,常,乐,于,时,傅,皮,卞,齐,康,伍,余,元,卜,顾,孟,平,黄, 和,穆,萧,尹,姚,邵,湛,汪,祁,毛,禹,狄,米,贝,明,臧,计,伏,成,戴,谈,宋,茅,庞,熊,纪,舒,屈,项,祝,董,梁, 杜,阮,蓝,闵,席,季,麻,强,贾,路,娄,危,江,童,颜,郭,梅,盛,林,刁,钟,徐,丘,骆,高,夏,蔡,田,樊,胡,凌,霍, 虞,万,支,柯,昝,管,卢,莫,经,房,裘,缪,干,解,应,宗,丁,宣,贲,邓,郁,单,杭,洪,包,诸,左,石,崔,吉,钮,龚, 程,嵇,邢,滑,裴,陆,荣,翁,荀,羊,於,惠,甄,麴,家,封,芮,羿,储,靳,汲,邴,糜,松,井,段,富,巫,乌,焦,巴,弓, 牧,隗,山,谷,车,侯,宓,蓬,全,郗,班,仰,秋,仲,伊,宫,宁,仇,栾,暴,甘,钭,厉,戌,祖,武,符,刘,景,詹,束,龙, 叶,幸,司,韶,郜,黎,蓟,薄,印,宿,白,怀,蒲,邰,从,鄂,索,咸,籍,赖,卓,蔺,屠,蒙,池,乔,阴,郁,胥,能,苍,双, 闻,莘,党,翟,谭,贡,劳,逢,姬,申,扶,堵,冉,宰,郦,雍,郤,璩,桑,桂,濮,牛,寿,通,边,扈,燕,冀,郏,浦,尚,农, 温,别,庄,晏,柴,瞿,阎,充,慕,连,茹,习,宦,艾,鱼,容,向,古,易,慎,戈,廖,庾,终,暨,居,衡,步,都,耿,满,弘, 匡,国,文,寇,广,禄,阙,东,欧,殳,沃,利,蔚,越,菱,隆,师,巩,厍,聂,晃,勾,敖,融,冷,訾,辛,阚,那,简,饶,空, 曾,毋,沙,乜,养,鞠,须,丰,巢,关,蒯,相,查,后,荆,红,游,竺,权,逯,盖,益,桓,公, 万俟,司马,上官,欧阳,夏侯,诸葛,闻人,东方,赫连,皇甫,尉迟,公羊,澹台,公冶,宗政,濮阳,淳于,单于,太叔,申屠,公孙,仲孙,轩辕,令狐,钟离,宇文,长孙,慕容,司徒,司空".Split(',');
			string[] lastNames = @"努,迪,立,林,维,吐,丽,新,涛,米,亚,克,湘,明,白,玉,代,孜,霖,霞,加,永,卿,约,小,刚,光,峰,春,基,木,国,娜,晓,兰,阿,伟,英,元,音,拉,亮,玲,木,兴,成,尔,远,东,华,旭,迪,吉,高,翠,莉,云,华,军,荣,柱,科,生,昊,耀,汤,胜,坚,仁,学,荣,延,成,庆,音,初,杰,宪,雄,久,培,祥,胜,梅,顺,涛,西,库,康,温,校,信,志,图,艾,赛,潘,多,振,伟,继,福,柯,雷,田,也,勇,乾,其,买,姚,杜,关,陈,静,宁,春,马,德,水,梦,晶,精,瑶,朗,语,日,月,星,河,飘,渺,星,空,如,萍,棕,影,南,北".Split(',');
			Random rand = new Random();
			int totalLength = rand.Next(2, 4);
			string name = firstNames[rand.Next(firstNames.Length)];
			while (name.Length < totalLength)
			{
				name += lastNames[rand.Next(lastNames.Length)];
			}
			return name;
		}

		///// <summary>
		///// 生成随机中文字符
		///// 
		///// gb2312 80
		///// 　　01-09区为特殊符号。 　　
		///// 　　16-55区为一级汉字，按拼音排序。 　
		///// 　　56-87区为二级汉字，按部首/笔画排序。 　　
		///// 　　10-15区及88-94区则未有编码。 
		///// 所有数字都是从 1 开始
		///// 每个汉字及符号以两个字节来表示。
		///// 第一个字节称为“高位字节”（也称“区字节）”，upper byte
		///// 第二个字节称为“低位字节”（也称“位字节”）。low byte
		///// “高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0)，
		///// “低位字节”使用了0xA1-0xFE(把01-94加上 0xA0)。 
		///// 由于一级汉字从16区起始，汉字区的“高位字节”的范围是0xB0-0xF7，
		///// “低位字节”的范围是0xA1-0xFE，
		///// 占用的码位是 72*94=6768。
		///// 其中有5个空位是D7FA-D7FE(55区90-94)
		///// </summary>
		///// <param name="length"></param>
		///// <returns></returns>
		//public static string GetRandomStr(int length)
		//{
		//	if (length <= 0)
		//	{
		//		return string.Empty;
		//	}

		//	StringBuilder tempStr = new StringBuilder();

		//	//byte minUpper = 16;
		//	//byte maxUpper = 55;
		//	//byte rangeLow = 94;
		//	//int addParamer = 0xA0;

		//	//int tempUpper = maxUpper - minUpper + 1;
		//	//Encoding gb = Encoding.GetEncoding("gb2312");

		//	//for (int i = 0; i < length; i++)
		//	//{
		//	//	int rdUpperValue = Random(tempUpper) + minUpper;
		//	//	int rdLowValue;
		//	//	do
		//	//	{
		//	//		rdLowValue = Random(rangeLow) + 1;//索引从1开始，所以94种子生成的随机数+1
		//	//	}
		//	//	while (rdUpperValue == maxUpper && rdLowValue >= 90);//D7FA-D7FE是空位(55区90-94)

		//	//	rdUpperValue += addParamer;
		//	//	rdLowValue += addParamer;

		//	//	byte[] byteArray = new byte[] { (byte)rdUpperValue, (byte)rdLowValue };

		//	//	tempStr.Append(gb.GetString(byteArray));
		//	//}

		//	return tempStr.ToString();
		//}

		/// <summary>
		/// 生成随机手机号
		/// </summary>
		/// <returns></returns>
		public static string GetRandomMobile()
		{
			string[] prefix = "13,14,15,17,18,19".Split(',');
			Random rand = new Random();
			return prefix[rand.Next(prefix.Length)] + rand.Next(1, 10) + rand.Next(10, 100) + rand.Next(10, 100) + rand.Next(10, 100) + rand.Next(10, 100);
		}

		/// <summary>
		/// 生成随机邮箱地址
		/// </summary>
		/// <returns></returns>
		public static string GetRandomEmail()
		{
			string[] prefix = "13,14,15,17,18,19".Split(',');
			string[] postfix = "@qq.com,@139.com,@189.com,@126.com,@sina.com,@163.com,@gmail.com".Split(',');
			Random rand = new Random();
			return prefix[rand.Next(prefix.Length)] + rand.Next(1, 10) + rand.Next(10, 100) + rand.Next(10, 100) + rand.Next(10, 100) + rand.Next(10, 100) + postfix[rand.Next(postfix.Length)];
		}

		/// <summary>
		/// 随机生成身份证号码
		/// </summary>
		/// <param name="minAge"></param>
		/// <param name="maxAge"></param>
		/// <param name="gender">性别，null：性别不限；1：男性；2：女性</param>
		/// <returns></returns>
		public static string GetRandomIDCardNo(int minAge, int maxAge, int? gender)
		{
			string[] prefix = "11:北京,12:天津,13:河北,14:山西,15:内蒙,21:辽宁,22:吉林,23:黑龙江,31:上海,32:江苏,33:浙江,34:安徽,35:福建,36:江西,37:山东,41:河南,42:湖北,43:湖南,44:广东,45:广西,46:xx,50:xx,51:四川,52:贵州,53:云南,54:西藏,61:陕西,62:甘肃,63:青海,64:宁夏,65:新疆,71:xx,81:xx,82:xx,91:xx".Split(',');
			//todo:简单版本
			Random rand = new Random();
			string citycode = rand.Next(100, 10000).ToString().PadLeft(4, '0');
			DateTime dtNow = DateTime.Now;
			DateTime dtBirthEnd = dtNow.AddYears(0 - minAge);
			DateTime dtBirthStart = dtNow.AddYears(0 - maxAge);
			int totalDays = (int)((dtBirthEnd - dtBirthStart).TotalDays);
			DateTime dtBirth = dtBirthStart.AddDays(rand.Next(totalDays));
			int serial = rand.Next(1, 1000);
			if (gender.HasValue)
			{
				if (gender == 1)
				{
					while (serial % 2 != 0)
					{
						serial = rand.Next(1, 1000);
					}
				}
				else
				{
					while (serial % 2 == 0)
					{
						serial = rand.Next(1, 1000);
					}
				}
			}
			string idcardno = prefix[rand.Next(0, prefix.Length)].Substring(0, 2) + citycode + dtBirth.ToString("yyyyMMdd") + serial.ToString().PadLeft(3, '0');
			return idcardno + IDCardHelper.GetIDCardNoCRC(idcardno);
		}

		/// <summary>
		/// 生成随机身份证号
		/// </summary>
		/// <returns></returns>
		public static string GetRandomIDCardNo()
		{
			return GetRandomIDCardNo(18, 80, null);
		}
	}
}
